package com.cj.ai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cj.ai.AiProperties;
import com.cj.ai.domain.*;
import com.cj.ai.service.IModelsService;
import com.cj.ai.service.IRecordsService;
import com.cj.common.constant.AiConstants;
import com.cj.common.core.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author cc
 * @date 2024-08-21 20:20
 **/
@Service
@EnableConfigurationProperties(AiProperties.class)
public class AiService {

    @Autowired
    RedisCache redisCache;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    AiProperties aiProperties;
    @Autowired
    IModelsService modelsService;

    public MpAnswer chat(MpRequest mpRequest, String openid) {

        // ai大模型认证 ，， 获取 accessToken，，， accessToken存到redis上，，

        String accessToken = getAccessToken();

        // 根据小程序传递的 模型名称，，查询模型的信息
        Models models = getModels(mpRequest.getModelName());


        // 调用ai接口
        // 获取之前的聊天
        List<AiChatMessage> messages = loadChatMessage(mpRequest.getSessionId());

        // 构建请求
        AiChatMessage message = new AiChatMessage();
        message.setRole(AiConstants.MESSAGE_ROLE_USER);

        // 前端可以要题目，，， 也可以要答案，，， 两种不同的提示词
        if (mpRequest.getType().equals(AiConstants.MP_REQUEST_TYPE_Q)){
            // content 准确的分类，， 前端传过来的内容，，提问的是固定的
            message.setContent(String.format(models.getQuestionPrompt(),mpRequest.getContent()));
        }else if (mpRequest.getType().equals(AiConstants.MP_REQUEST_TYPE_A)){
            message.setContent(String.format(models.getAnswerPrompt(),mpRequest.getContent()));
        }

        // 带上之前的message，发送请求
        messages.add(message);
        AiRequestBody aiRequestBody = new AiRequestBody();
        aiRequestBody.setMessages(messages);
        // 模型人设 例如：你是xxx公司制作的AI助手，说明：长度限制，message中的content总长度和system字段总内容不能超过24000个字符，且不能超过6144 tokens
        aiRequestBody.setSystem(models.getRole());
        aiRequestBody.setUser_id(openid);

//        String url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_speed?access_token={1}";
//        AiResponseBody responseBody = restTemplate.postForObject(models.getUrl(), aiRequestBody, AiResponseBody.class, accessToken);
        Object responseBody = restTemplate.postForObject(models.getUrl(), aiRequestBody, Object.class, accessToken);

        System.out.println("responseBody = " + responseBody);
//        AiChatMessage aiChatMessage = new AiChatMessage();
//        aiChatMessage.setRole(AiConstants.MESSAGE_ROLE_ASSISTANT);
//        aiChatMessage.setContent(responseBody.getResult());
//        messages.add(aiChatMessage);
//
//
//        cacheMessages(messages,mpRequest,openid);
//
//
//        MpAnswer mpAnswer = new MpAnswer();
//        mpAnswer.setType(AiConstants.MP_REQUEST_CHOICE);
////        redisCache.setCacheList()
//        mpAnswer.setContent(responseBody.getResult());
//
//        return mpAnswer;
        return null;
    }

    private void cacheMessages(List<AiChatMessage> messages, MpRequest mpRequest, String openid) {
        redisCache.setCacheList(AiConstants.AI_SESSION_PREFIX + mpRequest.getSessionId(), messages);

        // 存最后两条，， 一问一答
        recordsService.saveMessages(mpRequest,messages.subList(messages.size()-2,messages.size()),openid);
    }

    private List<AiChatMessage> loadChatMessage(String sessionId) {
        List<AiChatMessage> cacheList = redisCache.getCacheList(AiConstants.AI_SESSION_PREFIX + sessionId);
        if (cacheList == null ||  cacheList.size() == 0){
            cacheList = loadMessageFromDb(sessionId);
            if (cacheList == null){
                return new ArrayList<>();
            }
        }
        return cacheList;
    }
    @Autowired
    IRecordsService recordsService;

    private List<AiChatMessage> loadMessageFromDb(String sessionId) {
        List<Records> list = recordsService.list(new LambdaQueryWrapper<Records>()
                .eq(Records::getDelFlag, 1).eq(Records::getSessionId, sessionId));

       return list.stream().map(item->{
            AiChatMessage aiChatMessage = new AiChatMessage();
            aiChatMessage.setRole(item.getRole());
            aiChatMessage.setContent(item.getContent());
            return aiChatMessage;
        }).collect(Collectors.toList());
    }

    private Models getModels(String modelName) {
        // 没有传获取 默认的
        if (modelName == null || "".equals(modelName)){
            modelName = AiConstants.DEFAULT_AI_MODEL;
        }
        // 每提问一次，查数据模型，不太现实，，存入redis
        Models models = redisCache.getCacheMapValue(AiConstants.AI_MODEL_NAMES, modelName);
        if (models == null){
            LambdaQueryWrapper<Models> qw = new LambdaQueryWrapper<>();
            qw.eq(Models::getDelFlag,1);
            qw.eq(Models::getName,modelName);
//            qw.select()
            models = modelsService.getOne(qw);

            if (models == null){
                throw new RuntimeException("模型不存在");
            }else{
                redisCache.setCacheMapValue(AiConstants.AI_MODEL_NAMES,modelName,models);
            }
        }

        return models;
    }

    private String getAccessToken() {

        String accessToken = redisCache.getCacheObject(AiConstants.AI_ACCESS_TOKEN_KEY);
        if (accessToken != null && accessToken.length() >0){
            return accessToken;
        }

        // 没有重新拿
        LinkedMultiValueMap<Object, Object> params = new LinkedMultiValueMap<>();
        params.add("client_id",aiProperties.getClientId());
        params.add("client_secret",aiProperties.getClientSecret());
//        params.add("grant_type",aiProperties.getClientSecret());
        // 获取accessToken 有效期30天
        Map map = restTemplate.postForObject(aiProperties.getAccessTokenUrl(),null,Map.class,aiProperties.getClientId(),aiProperties.getClientSecret());

        String token = (String) map.get("access_token");

        // 存入redis
        redisCache.setCacheObject(AiConstants.AI_ACCESS_TOKEN_KEY,token,29, TimeUnit.DAYS);

        return token;

    }
}
